home *** CD-ROM | disk | FTP | other *** search
- /* LedClock (C)1987 Ali T. Ozer. A clock program for interlaced screens. */
-
- #include <exec/types.h>
- #include <functions.h>
- #include <intuition/intuition.h>
- #include <exec/devices.h>
- #include <devices/timer.h>
- #include <graphics/gfxmacros.h>
-
- /* LedClock is freely distributable and NOT for sale.
- **
- ** Author: Ali T. Ozer, ARPA: ali@score.stanford.edu,
- ** REAL: Box 7703, Stanford, CA 94309
- **
- ** A clock program for interlaced screens. This one uses
- ** numbers that resemble the numbers used in 7-segment LED and LCD
- ** clock displays. Various options are provided as compile time "#define"s:
- **
- ** TWENTYFOURHOUR 0 or 1, determines if the clock is 24-hour or not
- ** WINDOWXLOC starting X location for the window in the WB screen
- ** WINDOWYLOC starting Y location for the window in the WB screen
- ** FANCYPANIC 0 or 1, determines if a error message box is shown in
- ** case the clock can't run...
- **
- ** LedClock works best with interlaced screens --- It will look ugly on a
- ** "normal" WorkBench screen. (It will probably look fine on a lo-res, non
- ** interlaced screen, except it will be too big, way too big.)
- **
- ** LedClock can be compiled by Manx 3.40a. Use the "+c" and "+d" switches
- ** while linking to assure that the static images go into CHIP ram:
- **
- ** cc ledclock.c
- ** ln +cd ledclock.o -lc
- ** run ledclock
- **
- ** During linking you'll get warnings about _cli_parse and _wb_parse being
- ** redefined; you can safely ignore these messages.
- **
- ** Various corners have been cut from this program to make the executable small.
- ** With Manx 3.40a, the executable is somewhere around 3.1 Kbytes. One can
- ** probably achieve half that size in assembly.
- **
- ** Programmers might wish to fool around with the code to customize the
- ** clock. It's amazing how many parameters one can think of if one tries
- ** to make a general program... So, rather than trying to provide zillions
- ** of command line arguments, I took the easy way out and just threw out
- ** all generality... If you wish to create your customized clocks from
- ** this code, feel free to do so --- but please keep my original copyright
- ** notice (in the screen title bar) intact, along with any additional
- ** copyright notices you might add.
- */
-
- /* The next few define's can be changed for different runtime parameters... */
-
- #define TWENTYFOURHOUR 1
- #define FANCYPANIC 0
- #define WINDOWXLOC 20
- #define WINDOWYLOC 14
-
- #define COPYRIGHT "LedClock 1.0 (C)1987 Ali T. Ozer"
-
- #if FANCYPANIC
- #define Panic(arg) WarnUser(arg)
- #else
- #define Panic(arg) CloseThings(1)
- #endif
-
- #define DIGITMAXX 18
- #define DIGITMAXY 32
-
- #define WINDOWX 0
- #define WINDOWY 9
- #define DIGIT1X (WINDOWX + 3)
- #define DIGIT2X (DIGIT1X + DIGITMAXX + 3)
- #define DIGIT3X (DIGIT2X + DIGITMAXX + 10)
- #define DIGIT4X (DIGIT3X + DIGITMAXX + 3)
- #define DIGITY (WINDOWY + 3)
- #define WINDOWWIDTH (DIGIT4X + DIGITMAXX + 3)
- #define WINDOWHEIGHT (DIGITY + DIGITMAXY + 3)
- #define COLONX (DIGIT3X - 6)
- #define COLONY (DIGITY + 11)
-
- /* The "leds" (the segments making up the digits) are named in the standard
- ** (clockwise) fashion, with a = top led, b = right top, ... f = left top, and
- ** g = middle.
- **
- ** The following describes the vertical leds ("b", "c", "e", and "f")
- */
- USHORT vled [] = {
- 0xdfff, 0x8fff, 0x8fff, 0x8fff, 0x8fff, 0x8fff, 0x8fff,
- 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0xbfff
- };
-
- /* The following is the bitmap description of leds a and d.
- */
- USHORT hled [] = {0x807f, 0x003f, 0x807f};
-
- /* The following is the bitmap description of the middle ("g") led.
- */
- USHORT mled [] = {0x80ff, 0x007f, 0x80ff};
-
- /* The following describes the bitmap for the colon and the image.
- */
- USHORT colondata [] = {
- 0x8fff, 0x8fff, 0x8fff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0x1fff, 0x1fff, 0x1fff
- };
-
- struct Image colon = { 0, 0, 4, 11, 1, colondata, 1, 0, NULL};
-
- /* The following describes the Image structures for all 7 leds, "a".."g"
- */
- struct Image leds [] = {
- { 6, 0, 10, 3, 1, &hled[0], 1, 0, NULL},
- {15, 2, 4, 14, 1, &vled[0], 1, 0, NULL},
- {13, 17, 4, 14, 1, &vled[0], 1, 0, NULL},
- { 3, 30, 10, 3, 1, &hled[0], 1, 0, NULL},
- { 0, 17, 4, 14, 1, &vled[0], 1, 0, NULL},
- { 2, 2, 4, 14, 1, &vled[0], 1, 0, NULL},
- { 5, 15, 9, 3, 1, &mled[0], 1, 0, NULL}
- };
-
- /* In the following each byte determines what leds are lit for the
- ** corresponding digit. The bits are ordered "xgfedcba" and a 1 means the
- ** led is lit.
- */
- UBYTE lled [] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
-
- struct Window *MyWin;
- struct RastPort *MyRP;
- struct Library *IntuitionBase;
- struct Library *GfxBase;
- struct timerequest MyTR;
- unsigned long WindowSig, TimerSig;
- int curminutes;
-
- /* Draw digit puts a 7-segment digit at the specified location. If digit is
- ** negative, then the area is erased but nothing is drawn.
- */
- DrawDigit (rp, digit, xloc, yloc)
- struct RastPort *rp;
- int digit, xloc, yloc;
- {
- register int ledmask, ledcnt = 0;
-
- /* First erase it */
- RectFill (rp, (long)xloc, (long)yloc,
- (long)(xloc + DIGITMAXX), (long)(yloc + DIGITMAXY));
-
- if (digit >= 0) {
- ledmask = lled[digit];
- while (ledcnt != 7) {
- if (ledmask & 1) DrawImage (rp, &leds[ledcnt], (long)xloc, (long)yloc);
- ledcnt++; ledmask >>= 1;
- }
- }
- }
-
- /* OpenTimer will open the timer device and also do all the initialization
- ** necessary to send timer requests...
- */
- OpenTimer (tr)
- struct timerequest *tr;
- {
- struct MsgPort *timerport;
-
- while ((timerport = CreatePort (NULL, 0L)) == NULL) Panic ("No port");
-
- OpenDevice (TIMERNAME, UNIT_VBLANK, tr, 0L);
- tr->tr_node.io_Message.mn_ReplyPort = timerport;
- tr->tr_node.io_Command = TR_ADDREQUEST;
-
- }
-
- /* OpenThings opens the Amiga libraries, the window. and the timer.
- ** If something goes wrong, a requester will pop up to warn the user.
- ** (If FANCYPANIC is defined as zero, then no requester pops up --- the
- ** program just quits.)
- */
- OpenThings ()
- {
- static struct NewWindow MyWinInfo =
- { WINDOWXLOC, WINDOWYLOC, WINDOWWIDTH, WINDOWHEIGHT, /* Lft,Top,Wd,Hgt */
- -1,-1, /* Detail pen, Block pen (-1 = use screens) */
- CLOSEWINDOW, /* IDCMPflags */
- SMART_REFRESH | WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | NOCAREREFRESH,
- NULL, NULL, NULL, /* FirstGadget, Menu Checkmark, Title */
- NULL, NULL, /* Screen, Bitmap */
- 0, 0, 0, 0, /* Min Width/Height Max Width/Height */
- WBENCHSCREEN /* Type */
- };
-
- if (((IntuitionBase = OpenLibrary("intuition.library",0L)) == NULL) ||
- ((GfxBase = OpenLibrary("graphics.library",0L)) == NULL)) CloseThings (1);
-
- while (!(MyWin = OpenWindow(&MyWinInfo))) Panic ("No window");
- SetWindowTitles (MyWin, NULL, COPYRIGHT);
-
- MyRP = MyWin->RPort;
- WindowSig = 1L << MyWin->UserPort->mp_SigBit;
-
- SetOPen (MyRP, 1L);
- SetAPen (MyRP, 1L);
-
- OpenTimer(&MyTR);
- TimerSig = 1L << MyTR.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
- }
-
- /* SendTimerRequest sends a timer request for the indicated amount of seconds.
- ** Assumes the timer request block pointed to by tr has already been properly
- ** setup --- including the io_Command field.
- */
- SendTimerRequest (tr, seconds)
- struct timerequest *tr;
- unsigned long seconds;
- {
- tr->tr_time.tv_micro = 0L;
- tr->tr_time.tv_secs = seconds;
- SendIO (tr);
- }
-
- #if FANCYPANIC
-
- /* WarnUser is called when something goes wrong during initialization.
- ** WarnUser assumes Intuition is opened! (Now if that's not the case,
- ** then you're in trouble...)
- */
-
- WarnUser (reason)
- UBYTE *reason;
- {
- static struct IntuiText postxt = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Retry",NULL};
- static struct IntuiText negtxt = {3,1,COMPLEMENT,4,4,NULL,(UBYTE *)"Sigh",NULL};
- static struct IntuiText bodytxt = {3,1,COMPLEMENT,4,6,NULL,NULL,NULL};
-
- bodytxt.IText = reason;
- if (AutoRequest (NULL,&bodytxt,&postxt,&negtxt,0L,0L,300L,60L) == FALSE)
- CloseThings (1);
- }
-
- #endif
-
- /* CloseTimer closes the timer pointed to by tr. If no reply port is present,
- ** then CloseTimer assumes the timer was never opened.
- */
- CloseTimer (tr)
- struct timerequest *tr;
- {
- struct MsgPort *msgp;
- if (msgp = tr->tr_node.io_Message.mn_ReplyPort) {
- DeletePort (msgp);
- CloseDevice (tr);
- }
- }
-
- /* CloseThings releases all the resources obtained by the program.
- */
- CloseThings(error_code)
- int error_code;
- {
- CloseTimer(&MyTR);
- if (MyWin) CloseWindow(MyWin);
- if (GfxBase) CloseLibrary(GfxBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- exit (error_code);
- }
-
- static int ht = -1, ho = -1, mt = -1, mo = -1;
-
- /* WriteTime writes out the new time.
- */
- WriteTime (minutes)
- int minutes;
- {
- int hours, htens, hones, mtens, mones;
-
- #if TWENTYFOURHOUR
- hours = minutes / 60;
- #else
- hours = (minutes / 60 + 11) % 12 + 1;
- #endif
-
- /* AM if minutes < 720, but we don't worry about this... */
-
- if ((htens = hours / 10) != ht)
- DrawDigit (MyRP, ((ht = htens) ? ht : -1), DIGIT1X, DIGITY);
- if ((hones = hours % 10) != ho)
- DrawDigit (MyRP, ho = hones, DIGIT2X, DIGITY);
- if ((mtens = (minutes % 60) / 10) != mt)
- DrawDigit (MyRP, mt = mtens, DIGIT3X, DIGITY);
- if ((mones = (minutes % 10)) != mo)
- DrawDigit (MyRP, mo = mones, DIGIT4X, DIGITY);
- }
-
- /* ShowTheTime reads the time, updates the display, and sends a new timer
- ** request.
- */
- ShowTheTime ()
- {
- long timevec[3];
-
- DateStamp (&timevec[0]);
- curminutes = (int)(timevec[1]);
- WriteTime (curminutes);
- /* Timer request for the next top of minute */
- SendTimerRequest (&MyTR, 60L - (long)(timevec[2] / 50L));
- }
-
- main ()
- {
- struct Task *me;
-
- OpenThings ();
-
- /* Bump the priority up to 5. Not too serious, as under normal conditions
- ** this program will wake up only every 60 seconds.
- */
- if (me = FindTask (NULL)) SetTaskPri (me, 5L);
-
- /* Clear the window and draw in the ":".
- */
- RectFill (MyRP, (long)WINDOWX, (long)WINDOWY,
- WINDOWWIDTH-1L, WINDOWHEIGHT-1L);
- DrawImage (MyRP, &colon, (long)COLONX, (long)COLONY);
-
- /* Now sit down, relax, and wait for either an IDCMP or a timer event...
- */
- while (1) {
- ShowTheTime ();
- if (Wait (WindowSig | TimerSig) & TimerSig)
- (void) GetMsg (MyTR.tr_node.io_Message.mn_ReplyPort);
- else {
- AbortIO (&MyTR); /* Don't even get the message, assume it's CLOSEWINDOW */
- CloseThings (0);
- }
- }
- }
-
-
-
- /* Including the following two lines prevents the linker from bringing in
- ** the two functions _wb_parse and _cli_parse called by the initialization
- ** code in _main. Reduces code size by about 900 bytes for Manx 3.40a.
- */
- void _wb_parse () {}
- void _cli_parse () {}
-